package gui;

import player.*;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;

public class mainGui extends WindowAdapter implements WindowListener, ActionListener, Runnable {

	private Thread reader;
	private Thread reader2;
	private boolean quit;
	
	public InetAddress host = null;
					
	private final PipedInputStream pin=new PipedInputStream(); 
	private final PipedInputStream pin2=new PipedInputStream(); 
	
	private static volatile mainGui instance = null;
    /**
     * Creates new form mainGui
     */
    private mainGui() {
        initComponents();
		reader=new Thread(this);
		reader.setDaemon(true);	
		reader.start();	
		
		reader2=new Thread(this);	
		reader2.setDaemon(true);	
		reader2.start();
		quit=false;
		this.activateConsole();
    }
    

    
    public static mainGui getInstance() {
        if (instance == null){
            synchronized (mainGui.class){
                    if (instance == null){
                        instance = new mainGui();
                    }
        }}
        return instance;
    }    


    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        serverConButton = new javax.swing.JButton();
        userNameText = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        textArea = new javax.swing.JTextArea();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        portInput = new javax.swing.JTextField();
        readyButton = new javax.swing.JButton();
        hostInput = new javax.swing.JTextField();
        MenuBar = new javax.swing.JMenuBar();
        FileMenu = new javax.swing.JMenu();
        HelpMenu = new javax.swing.JMenu();
        
        this.frame = new JFrame("Scramble-Words");
        // operation to do when the window is closed.
        this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        this.frame.getContentPane().setLayout(new BorderLayout());
        //this.frame.getContentPane().add(frame);
        this.frame.pack();        
        this.frame.addWindowListener(this);
        this.frame.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        this.frame.setPreferredSize(new java.awt.Dimension(530, 418));
        
        this.FileMenu.setText("File");
        this.HelpMenu.setText("Help");
        JMenuItem exitAction = new JMenuItem();
        JMenuItem aboutAction = new JMenuItem();
        exitAction.setText("Exit");
        aboutAction.setText("About...");
        this.FileMenu.add(exitAction);
        this.HelpMenu.add(aboutAction);
        this.MenuBar.add(FileMenu);
        this.MenuBar.add(HelpMenu);
        
        exitAction.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				exitActionActionPerformed(evt);
			}
		});
        
        aboutAction.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				aboutActionActionPerformed(evt);
			}
		});
        
        this.frame.setJMenuBar(MenuBar);

        serverConButton.setFont(new java.awt.Font("Tempus Sans ITC", 1, 14)); // NOI18N
        serverConButton.setText("Connect to Server");
        serverConButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				serverConButtonActionPerformed(evt);
			}
		});
        
        hostInput.setText("192.168.5.102");

        userNameText.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        userNameText.setText("player");
        
        hostInput.setHorizontalAlignment(javax.swing.JTextField.LEFT);

        jLabel1.setFont(new java.awt.Font("Tahoma", 2, 14)); // NOI18N
        jLabel1.setText("Set Host:");
        
        portInput.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        
        jLabel4.setFont(new java.awt.Font("Tahoma", 2, 14));
        jLabel4.setText("Set Port:");

        textArea.setEditable(false);
        textArea.setColumns(20);
        textArea.setRows(5);
        textArea.setWrapStyleWord(true);
        textArea.setFocusable(false);
        textArea.setName(""); // NOI18N
        textArea.setVerifyInputWhenFocusTarget(false);
        textArea.setAutoscrolls(true);
        jScrollPane1.setViewportView(textArea);
        jScrollPane1.setAutoscrolls(true);

        jLabel2.setText("Enter your Name:");

        readyButton.setFont(new java.awt.Font("Trebuchet MS", 3, 18)); // NOI18N
        readyButton.setText("Click when Ready!");
        readyButton.setEnabled(false);
        readyButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				readyButtonActionPerformed(evt);
			}
		});

		jLabel3.setFont(new java.awt.Font("Segoe UI", 2, 14));
		jLabel3.setText("Scramble-Words!");

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
				frame.getContentPane());
		frame.getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(jScrollPane1,
										javax.swing.GroupLayout.DEFAULT_SIZE,
										436, Short.MAX_VALUE).addContainerGap())
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(jLabel3)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED,
										225, Short.MAX_VALUE)
								.addComponent(jLabel1)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(hostInput,
										javax.swing.GroupLayout.PREFERRED_SIZE,
										71,
										javax.swing.GroupLayout.PREFERRED_SIZE)
								.addContainerGap())
				.addGroup(
						layout.createSequentialGroup()
								.addGap(146, 146, 146)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createSequentialGroup()
																.addGap(31, 31,
																		31)
																.addComponent(
																		jLabel2))
												.addGroup(
														layout.createSequentialGroup()
																.addGap(12, 12,
																		12)
																.addComponent(
																		userNameText,
																		javax.swing.GroupLayout.PREFERRED_SIZE,
																		130,
																		javax.swing.GroupLayout.PREFERRED_SIZE))
												.addComponent(
														serverConButton,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														157,
														javax.swing.GroupLayout.PREFERRED_SIZE))
								.addContainerGap(157, Short.MAX_VALUE))
				.addGroup(
						layout.createSequentialGroup()
								.addGap(113, 113, 113)
								.addComponent(readyButton,
										javax.swing.GroupLayout.DEFAULT_SIZE,
										223, Short.MAX_VALUE)
								.addGap(124, 124, 124)));
		layout.setVerticalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createSequentialGroup()
																.addGap(46, 46,
																		46)
																.addComponent(
																		jLabel2)
																.addPreferredGap(
																		javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																.addComponent(
																		userNameText,
																		javax.swing.GroupLayout.PREFERRED_SIZE,
																		javax.swing.GroupLayout.DEFAULT_SIZE,
																		javax.swing.GroupLayout.PREFERRED_SIZE)
																.addPreferredGap(
																		javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																.addComponent(
																		serverConButton))
												.addGroup(
														layout.createParallelGroup(
																javax.swing.GroupLayout.Alignment.BASELINE)
																.addComponent(
																		jLabel3)
																.addComponent(
																		jLabel1)
																.addComponent(
																		hostInput,
																		javax.swing.GroupLayout.PREFERRED_SIZE,
																		javax.swing.GroupLayout.DEFAULT_SIZE,
																		javax.swing.GroupLayout.PREFERRED_SIZE)))
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(readyButton,
										javax.swing.GroupLayout.PREFERRED_SIZE,
										33,
										javax.swing.GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(jScrollPane1,
										javax.swing.GroupLayout.DEFAULT_SIZE,
										211, Short.MAX_VALUE).addContainerGap()));

		serverConButton.getAccessibleContext().setAccessibleName("");
		readyButton.getAccessibleContext().setAccessibleName("");

		frame.pack();
		frame.setLocationRelativeTo(null);
	}// </editor-fold>//GEN-END:initComponents
    
	private synchronized void serverConButtonActionPerformed(java.awt.event.ActionEvent evt) {
		try{
			InetAddress temp = InetAddress.getByName(hostInput.getText());
			System.out.println("Connecting to Host: "+temp);
			player.getInstance().connectToServer(temp);
			player.getInstance().setName(userNameText.getText());
			this.changeServerConButtonStat(false);
		}
		catch(UnknownHostException e){
			System.err.println("Host name is not valid. Please check the host input.");
		}
	}
	
	private synchronized void readyButtonActionPerformed(java.awt.event.ActionEvent evt) {
		player.getInstance().sendReady();
		this.changeReadyButtonStat(false);
	}
	
	private synchronized void exitActionActionPerformed(java.awt.event.ActionEvent evt){
		System.exit(0);
	}
	
	private synchronized void aboutActionActionPerformed(java.awt.event.ActionEvent evt){
		JOptionPane.showMessageDialog(frame, "Programmed and Developed by:\nSameer Makladeh & Rochai Ben-Mordechi.\nSpring Semester 2012");
	}
	
 // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JFrame frame;
    private javax.swing.JButton serverConButton;
    private javax.swing.JButton readyButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField userNameText;
    private javax.swing.JTextArea textArea;
    private javax.swing.JTextField hostInput;
    private javax.swing.JTextField portInput;
    private javax.swing.JMenuBar MenuBar;
    private javax.swing.JMenu FileMenu;
    private javax.swing.JMenu HelpMenu;
    // End of variables declaration//GEN-END:variables
    
   
   public void display(){
       this.frame.setVisible(true);
   }
   
   public synchronized void activateConsole(){ //console display was revised from an existing opensource version found online.
	   try
		{
			PipedOutputStream pout=new PipedOutputStream(this.pin);
			System.setOut(new PrintStream(pout,true)); 
		} 
		catch (java.io.IOException io)
		{
			textArea.append("Couldn't redirect STDOUT to this console\n"+io.getMessage());
		}
		catch (SecurityException se)
		{
			textArea.append("Couldn't redirect STDOUT to this console\n"+se.getMessage());
	    } 
		
		try 
		{
			PipedOutputStream pout2=new PipedOutputStream(this.pin2);
			System.setErr(new PrintStream(pout2,true));
		} 
		catch (java.io.IOException io)
		{
			textArea.append("Couldn't redirect STDERR to this console\n"+io.getMessage());
		}
		catch (SecurityException se)
		{
			textArea.append("Couldn't redirect STDERR to this console\n"+se.getMessage());
	    }
   }

@Override
public synchronized void windowActivated(WindowEvent e) {
	// TODO Auto-generated method stub
}

@Override
public synchronized void windowClosed(WindowEvent e) {
	quit=true;
	this.notifyAll(); // stop all threads
	try { reader.join(1000); pin.close();   } catch (Exception ex){}		
	try { reader2.join(1000); pin2.close(); } catch (Exception ex){}
	try { clientToServer.getInstance().closeConnection(); } catch (Exception ex){}
	System.exit(0);
}

@Override
public synchronized void windowClosing(WindowEvent e) {
	this.frame.setVisible(false); // default behavior of JFrame	
	this.frame.dispose();
}

@Override
public synchronized void windowDeactivated(WindowEvent e) {
	// TODO Auto-generated method stub
	
}

@Override
public synchronized void windowDeiconified(WindowEvent e) {
	// TODO Auto-generated method stub
	
}

@Override
public synchronized void windowIconified(WindowEvent e) {
	// TODO Auto-generated method stub
	
}

@Override
public synchronized void windowOpened(WindowEvent e) {
	// TODO Auto-generated method stub
	
}

public void terminateMainGui(){
	this.frame.dispose();
}

@Override
public  synchronized void run() {
	try{			
		while (Thread.currentThread()==reader){
			try { this.wait(100);}catch(InterruptedException ie) {}
			if (pin.available()!=0)
			{
				String input=this.readLine(pin);
				textArea.append(input);
			}
			if (quit) return;
		}
	
		while (Thread.currentThread()==reader2){
			try { this.wait(100);}catch(InterruptedException ie) {}
			if (pin2.available()!=0)
			{
				String input=this.readLine(pin2);
				textArea.append(input);
			}
			if (quit) return;
		}			
	} 
	catch (Exception e)
	{
		textArea.append("\nConsole has reported an Internal error.");
		textArea.append("\nThe error is: "+e);
	}	
}

public synchronized String readLine(PipedInputStream in) throws IOException
{
	String input="";
	do
	{
		int available=in.available();
		if (available==0) break;
		byte b[]=new byte[available];
		in.read(b);
		input=input+new String(b,0,b.length);														
	}
	while( !input.endsWith("\n") &&  !input.endsWith("\r\n") && !quit);
	return input;
}




@Override
public void actionPerformed(ActionEvent arg0) {
	// TODO Auto-generated method stub
	
}

public void changeServerConButtonStat(boolean stat){
	this.serverConButton.setEnabled(stat);
}

public void changeReadyButtonStat(boolean stat){
	this.readyButton.setEnabled(stat);
}

public void setFrameVisibility(boolean vis){
	this.frame.setVisible(vis);
}

public void setHostInput(String input){
	this.hostInput.setText(input);
}
}

